#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

const std::string gpath = "/home/sh/linux";
int gprojId = 0x6666;
int gshmsize = 4096;
mode_t gmode = 0600;

std::string ToHex(key_t k)
{
	char buffer[64];
	snprintf(buffer, sizeof(buffer), "0x%x", k);
	return buffer;
}

class ShareMemory
{
private:
	void CreatShmHelper(int shmflag)
	{
		_key = ::ftok(gpath.c_str(), gprojId);
		if (_key < 0)
		{
			std::cerr << "ftok error" << std::endl;
			return;
		}
		_shmid = ::shmget(_key, gshmsize, shmflag);
		if (_shmid < 0)
		{
			std::cerr << "shmget error" << std::endl;
			return;
		}
		std::cout << "shmid: " << _shmid << std::endl;
	}

public:
	ShareMemory():_shmid(-1),_key(0),_addr(nullptr)
	{}
	~ShareMemory() {}
	void CreatShm()
	{
		if(_shmid == -1) //说明shm没有被创建过
			CreatShmHelper(IPC_CREAT | IPC_EXCL | gmode);
	}
	void GetShm()
	{
		CreatShmHelper(IPC_CREAT);
	}
	void AttachShm() // 挂接
	{
		_addr = shmat(_shmid, nullptr, 0); // 失败返回-1，为什么会失败？没有设置权限
		if ((long long)_addr == -1)
		{
			std::cout << "attach error" << std::endl;
		}
	}
	void DetachShm() //去关联
	{
		if(_addr != nullptr)
			::shmdt(_addr);
		std::cout << "detach done: " << std::endl;
	}
	void DeleteShm() // 删除
	{
		shmctl(_shmid, IPC_RMID, nullptr);
	}
	void* GetAddr()
	{
		return _addr;
	}
	void ShmMeta()
	{
		struct shmid_ds buffer;
		int n = ::shmctl(_shmid,IPC_STAT,&buffer);
		if(n < 0) return;

		std::cout << "###############" << std::endl;
		std::cout << buffer.shm_atime << std::endl;
		std::cout << buffer.shm_cpid << std::endl;
		std::cout << buffer.shm_ctime << std::endl;
		std::cout << buffer.shm_nattch << std::endl;
		std::cout << buffer.shm_perm.__key << std::endl;
		std::cout << "###############" << std::endl;
	}

private:
	int _shmid;
	key_t _key;
	void* _addr;
};


ShareMemory shm;


struct data
{
	char status[32];
	char lasttime[48];
	char image[4016];
};